{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# SF Bike Rentals"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture\n",
    "%pip install google-cloud-bigquery bokeh\n",
    "%load_ext google.cloud.bigquery"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "tags": [
     "parameters"
    ]
   },
   "outputs": [],
   "source": [
    "# cell has tag: \"parameters\", default if not provided\n",
    "start_date = \"2000-01-01\"\n",
    "end_date = \"2020-01-01\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Including rides between 2000-01-01 and 2020-01-01\n"
     ]
    }
   ],
   "source": [
    "params = {\n",
    "    \"start_date\": start_date, \n",
    "    \"end_date\": end_date\n",
    "}\n",
    "print(\"Including rides between {} and {}\".format(start_date, end_date))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bigquery sf_stations --params $params\n",
    "SELECT\n",
    "    stations.station_id,\n",
    "    stations.name,\n",
    "    stations.lat,\n",
    "    stations.lon,\n",
    "    COUNT(*) as count\n",
    "FROM\n",
    "    `bigquery-public-data.san_francisco_bikeshare.bikeshare_trips` as trips\n",
    "JOIN \n",
    "    `bigquery-public-data.san_francisco_bikeshare.bikeshare_station_info` as stations \n",
    "ON \n",
    "    trips.start_station_id = stations.station_id\n",
    "WHERE\n",
    "    stations.lat BETWEEN 37.7 AND 38.5 AND \n",
    "    stations.lon BETWEEN -122.5 AND -122.35 AND\n",
    "    trips.start_date BETWEEN TIMESTAMP( @start_date ) AND TIMESTAMP( @end_date )\n",
    "GROUP BY\n",
    "    stations.station_id, stations.name, stations.lat, stations.lon\n",
    "ORDER By\n",
    "    count DESC"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Top 10 Stations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "</style><table id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047\" ><thead>    <tr>        <th class=\"col_heading level0 col0\" >name</th>        <th class=\"col_heading level0 col1\" >count</th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                                <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row0_col0\" class=\"data row0 col0\" >Central Ave at Fell St</td>\n",
       "                        <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row0_col1\" class=\"data row0 col1\" >80370</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                                <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row1_col0\" class=\"data row1 col0\" >2nd St at Townsend St</td>\n",
       "                        <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row1_col1\" class=\"data row1 col1\" >56570</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                                <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row2_col0\" class=\"data row2 col0\" >San Francisco Caltrain Station 2  (Townsend St at 4th St)</td>\n",
       "                        <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row2_col1\" class=\"data row2 col1\" >50283</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                                <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row3_col0\" class=\"data row3 col0\" >8th St at Ringold St</td>\n",
       "                        <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row3_col1\" class=\"data row3 col1\" >46286</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                                <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row4_col0\" class=\"data row4 col0\" >Howard St at 8th St</td>\n",
       "                        <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row4_col1\" class=\"data row4 col1\" >45166</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                                <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row5_col0\" class=\"data row5 col0\" >Laguna St at Hayes St</td>\n",
       "                        <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row5_col1\" class=\"data row5 col1\" >43779</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                                <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row6_col0\" class=\"data row6 col0\" >Webster St at Grove St</td>\n",
       "                        <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row6_col1\" class=\"data row6 col1\" >41647</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                                <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row7_col0\" class=\"data row7 col0\" >11th St at Natoma St</td>\n",
       "                        <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row7_col1\" class=\"data row7 col1\" >39243</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                                <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row8_col0\" class=\"data row8 col0\" >McCoppin St at Valencia St</td>\n",
       "                        <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row8_col1\" class=\"data row8 col1\" >33035</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                                <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row9_col0\" class=\"data row9 col0\" >5th St at Brannan St</td>\n",
       "                        <td id=\"T_4398f1e4_4f31_11e9_ac09_42010a8a0047row9_col1\" class=\"data row9 col1\" >30195</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7f21e14f38d0>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "top = sf_stations[['name','count']].head(10)\n",
    "top.style.hide_index()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Station Map"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "\n",
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  var force = true;\n",
       "\n",
       "  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n",
       "    root._bokeh_onload_callbacks = [];\n",
       "    root._bokeh_is_loading = undefined;\n",
       "  }\n",
       "\n",
       "  var JS_MIME_TYPE = 'application/javascript';\n",
       "  var HTML_MIME_TYPE = 'text/html';\n",
       "  var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
       "  var CLASS_NAME = 'output_bokeh rendered_html';\n",
       "\n",
       "  /**\n",
       "   * Render data to the DOM node\n",
       "   */\n",
       "  function render(props, node) {\n",
       "    var script = document.createElement(\"script\");\n",
       "    node.appendChild(script);\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when an output is cleared or removed\n",
       "   */\n",
       "  function handleClearOutput(event, handle) {\n",
       "    var cell = handle.cell;\n",
       "\n",
       "    var id = cell.output_area._bokeh_element_id;\n",
       "    var server_id = cell.output_area._bokeh_server_id;\n",
       "    // Clean up Bokeh references\n",
       "    if (id != null && id in Bokeh.index) {\n",
       "      Bokeh.index[id].model.document.clear();\n",
       "      delete Bokeh.index[id];\n",
       "    }\n",
       "\n",
       "    if (server_id !== undefined) {\n",
       "      // Clean up Bokeh references\n",
       "      var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
       "      cell.notebook.kernel.execute(cmd, {\n",
       "        iopub: {\n",
       "          output: function(msg) {\n",
       "            var id = msg.content.text.trim();\n",
       "            if (id in Bokeh.index) {\n",
       "              Bokeh.index[id].model.document.clear();\n",
       "              delete Bokeh.index[id];\n",
       "            }\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "      // Destroy server and session\n",
       "      var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
       "      cell.notebook.kernel.execute(cmd);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when a new output is added\n",
       "   */\n",
       "  function handleAddOutput(event, handle) {\n",
       "    var output_area = handle.output_area;\n",
       "    var output = handle.output;\n",
       "\n",
       "    // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
       "    if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n",
       "      return\n",
       "    }\n",
       "\n",
       "    var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
       "      toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
       "      // store reference to embed id on output_area\n",
       "      output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "    }\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "      var bk_div = document.createElement(\"div\");\n",
       "      bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "      var script_attrs = bk_div.children[0].attributes;\n",
       "      for (var i = 0; i < script_attrs.length; i++) {\n",
       "        toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "      }\n",
       "      // store reference to server id on output_area\n",
       "      output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function register_renderer(events, OutputArea) {\n",
       "\n",
       "    function append_mime(data, metadata, element) {\n",
       "      // create a DOM node to render to\n",
       "      var toinsert = this.create_output_subarea(\n",
       "        metadata,\n",
       "        CLASS_NAME,\n",
       "        EXEC_MIME_TYPE\n",
       "      );\n",
       "      this.keyboard_manager.register_events(toinsert);\n",
       "      // Render to node\n",
       "      var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "      render(props, toinsert[toinsert.length - 1]);\n",
       "      element.append(toinsert);\n",
       "      return toinsert\n",
       "    }\n",
       "\n",
       "    /* Handle when an output is cleared or removed */\n",
       "    events.on('clear_output.CodeCell', handleClearOutput);\n",
       "    events.on('delete.Cell', handleClearOutput);\n",
       "\n",
       "    /* Handle when a new output is added */\n",
       "    events.on('output_added.OutputArea', handleAddOutput);\n",
       "\n",
       "    /**\n",
       "     * Register the mime type and append_mime function with output_area\n",
       "     */\n",
       "    OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "      /* Is output safe? */\n",
       "      safe: true,\n",
       "      /* Index of renderer in `output_area.display_order` */\n",
       "      index: 0\n",
       "    });\n",
       "  }\n",
       "\n",
       "  // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
       "  if (root.Jupyter !== undefined) {\n",
       "    var events = require('base/js/events');\n",
       "    var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  \n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  var NB_LOAD_WARNING = {'data': {'text/html':\n",
       "     \"<div style='background-color: #fdd'>\\n\"+\n",
       "     \"<p>\\n\"+\n",
       "     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
       "     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
       "     \"</p>\\n\"+\n",
       "     \"<ul>\\n\"+\n",
       "     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
       "     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
       "     \"</ul>\\n\"+\n",
       "     \"<code>\\n\"+\n",
       "     \"from bokeh.resources import INLINE\\n\"+\n",
       "     \"output_notebook(resources=INLINE)\\n\"+\n",
       "     \"</code>\\n\"+\n",
       "     \"</div>\"}};\n",
       "\n",
       "  function display_loaded() {\n",
       "    var el = document.getElementById(null);\n",
       "    if (el != null) {\n",
       "      el.textContent = \"BokehJS is loading...\";\n",
       "    }\n",
       "    if (root.Bokeh !== undefined) {\n",
       "      if (el != null) {\n",
       "        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
       "      }\n",
       "    } else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(display_loaded, 100)\n",
       "    }\n",
       "  }\n",
       "\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n",
       "    }\n",
       "    finally {\n",
       "      delete root._bokeh_onload_callbacks\n",
       "    }\n",
       "    console.info(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(js_urls, callback) {\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls == null || js_urls.length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    root._bokeh_is_loading = js_urls.length;\n",
       "    for (var i = 0; i < js_urls.length; i++) {\n",
       "      var url = js_urls[i];\n",
       "      var s = document.createElement('script');\n",
       "      s.src = url;\n",
       "      s.async = false;\n",
       "      s.onreadystatechange = s.onload = function() {\n",
       "        root._bokeh_is_loading--;\n",
       "        if (root._bokeh_is_loading === 0) {\n",
       "          console.log(\"Bokeh: all BokehJS libraries loaded\");\n",
       "          run_callbacks()\n",
       "        }\n",
       "      };\n",
       "      s.onerror = function() {\n",
       "        console.warn(\"failed to load library \" + url);\n",
       "      };\n",
       "      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
       "    }\n",
       "  };\n",
       "\n",
       "  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.4.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.0.4.min.js\"];\n",
       "\n",
       "  var inline_js = [\n",
       "    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "    \n",
       "    function(Bokeh) {\n",
       "      \n",
       "    },\n",
       "    function(Bokeh) {\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.4.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.4.min.css\");\n",
       "    }\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    \n",
       "    if ((root.Bokeh !== undefined) || (force === true)) {\n",
       "      for (var i = 0; i < inline_js.length; i++) {\n",
       "        inline_js[i].call(root, root.Bokeh);\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    } else if (force !== true) {\n",
       "      var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n",
       "      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
       "    }\n",
       "\n",
       "  }\n",
       "\n",
       "  if (root._bokeh_is_loading === 0) {\n",
       "    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
       "    run_inline_js();\n",
       "  } else {\n",
       "    load_libs(js_urls, function() {\n",
       "      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "      run_inline_js();\n",
       "    });\n",
       "  }\n",
       "}(window));"
      ],
      "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  var force = true;\n\n  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n    root._bokeh_onload_callbacks = [];\n    root._bokeh_is_loading = undefined;\n  }\n\n  \n\n  \n  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  var NB_LOAD_WARNING = {'data': {'text/html':\n     \"<div style='background-color: #fdd'>\\n\"+\n     \"<p>\\n\"+\n     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n     \"</p>\\n\"+\n     \"<ul>\\n\"+\n     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n     \"</ul>\\n\"+\n     \"<code>\\n\"+\n     \"from bokeh.resources import INLINE\\n\"+\n     \"output_notebook(resources=INLINE)\\n\"+\n     \"</code>\\n\"+\n     \"</div>\"}};\n\n  function display_loaded() {\n    var el = document.getElementById(null);\n    if (el != null) {\n      el.textContent = \"BokehJS is loading...\";\n    }\n    if (root.Bokeh !== undefined) {\n      if (el != null) {\n        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n      }\n    } else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(display_loaded, 100)\n    }\n  }\n\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n    }\n    finally {\n      delete root._bokeh_onload_callbacks\n    }\n    console.info(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(js_urls, callback) {\n    root._bokeh_onload_callbacks.push(callback);\n    if (root._bokeh_is_loading > 0) {\n      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls == null || js_urls.length === 0) {\n      run_callbacks();\n      return null;\n    }\n    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    root._bokeh_is_loading = js_urls.length;\n    for (var i = 0; i < js_urls.length; i++) {\n      var url = js_urls[i];\n      var s = document.createElement('script');\n      s.src = url;\n      s.async = false;\n      s.onreadystatechange = s.onload = function() {\n        root._bokeh_is_loading--;\n        if (root._bokeh_is_loading === 0) {\n          console.log(\"Bokeh: all BokehJS libraries loaded\");\n          run_callbacks()\n        }\n      };\n      s.onerror = function() {\n        console.warn(\"failed to load library \" + url);\n      };\n      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.getElementsByTagName(\"head\")[0].appendChild(s);\n    }\n  };\n\n  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.4.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.0.4.min.js\"];\n\n  var inline_js = [\n    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\n    \n    function(Bokeh) {\n      \n    },\n    function(Bokeh) {\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.4.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.4.min.css\");\n    }\n  ];\n\n  function run_inline_js() {\n    \n    if ((root.Bokeh !== undefined) || (force === true)) {\n      for (var i = 0; i < inline_js.length; i++) {\n        inline_js[i].call(root, root.Bokeh);\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    } else if (force !== true) {\n      var cell = $(document.getElementById(null)).parents('.cell').data().cell;\n      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n    }\n\n  }\n\n  if (root._bokeh_is_loading === 0) {\n    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n    run_inline_js();\n  } else {\n    load_libs(js_urls, function() {\n      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n      run_inline_js();\n    });\n  }\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "  <div class=\"bk-root\" id=\"4b4a4364-ad09-476f-a8ae-62d00dce8bda\" data-root-id=\"1005\"></div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "    \n",
       "  var docs_json = {\"ad50ef3a-52f0-401b-9c09-8bac8448aa7f\":{\"roots\":{\"references\":[{\"attributes\":{},\"id\":\"1036\",\"type\":\"LinearScale\"},{\"attributes\":{\"source\":{\"id\":\"1027\",\"type\":\"ColumnDataSource\"}},\"id\":\"1032\",\"type\":\"CDSView\"},{\"attributes\":{\"lat\":37.775,\"lng\":-122.42,\"zoom\":13},\"id\":\"1002\",\"type\":\"GMapOptions\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"1018\",\"type\":\"PanTool\"},{\"id\":\"1019\",\"type\":\"WheelZoomTool\"},{\"id\":\"1020\",\"type\":\"ResetTool\"},{\"id\":\"1021\",\"type\":\"HelpTool\"},{\"id\":\"1033\",\"type\":\"HoverTool\"}]},\"id\":\"1022\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"1039\",\"type\":\"Selection\"},{\"attributes\":{\"api_key\":\"AIzaSyDOwM8pTE_MGqXjrPCzAeNmVYln8t6aOpc\",\"below\":[{\"id\":\"1010\",\"type\":\"LinearAxis\"}],\"left\":[{\"id\":\"1015\",\"type\":\"LinearAxis\"}],\"map_options\":{\"id\":\"1002\",\"type\":\"GMapOptions\"},\"renderers\":[{\"id\":\"1010\",\"type\":\"LinearAxis\"},{\"id\":\"1015\",\"type\":\"LinearAxis\"},{\"id\":\"1031\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"1035\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"1022\",\"type\":\"Toolbar\"},\"x_range\":{\"id\":\"1003\",\"type\":\"Range1d\"},\"x_scale\":{\"id\":\"1038\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"1004\",\"type\":\"Range1d\"},\"y_scale\":{\"id\":\"1036\",\"type\":\"LinearScale\"}},\"id\":\"1005\",\"subtype\":\"GMap\",\"type\":\"GMapPlot\"},{\"attributes\":{\"dimension\":\"lat\"},\"id\":\"1014\",\"type\":\"MercatorTicker\"},{\"attributes\":{},\"id\":\"1040\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"plot\":null,\"text\":\"\"},\"id\":\"1035\",\"type\":\"Title\"},{\"attributes\":{\"palette\":[\"#440154\",\"#404387\",\"#29788E\",\"#22A784\",\"#79D151\",\"#FDE724\"]},\"id\":\"1001\",\"type\":\"LogColorMapper\"},{\"attributes\":{},\"id\":\"1038\",\"type\":\"LinearScale\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"name\",\"@name\"],[\"loc\",\"(@lat, @lon)\"],[\"count\",\"@count\"]]},\"id\":\"1033\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"1019\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"units\":\"screen\",\"value\":10},\"x\":{\"field\":\"lon\"},\"y\":{\"field\":\"lat\"}},\"id\":\"1030\",\"type\":\"Circle\"},{\"attributes\":{\"formatter\":{\"id\":\"1008\",\"type\":\"MercatorTickFormatter\"},\"plot\":{\"id\":\"1005\",\"subtype\":\"GMap\",\"type\":\"GMapPlot\"},\"ticker\":{\"id\":\"1009\",\"type\":\"MercatorTicker\"}},\"id\":\"1010\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"1020\",\"type\":\"ResetTool\"},{\"attributes\":{\"callback\":null},\"id\":\"1003\",\"type\":\"Range1d\"},{\"attributes\":{\"callback\":null},\"id\":\"1004\",\"type\":\"Range1d\"},{\"attributes\":{\"dimension\":\"lon\"},\"id\":\"1009\",\"type\":\"MercatorTicker\"},{\"attributes\":{},\"id\":\"1021\",\"type\":\"HelpTool\"},{\"attributes\":{},\"id\":\"1018\",\"type\":\"PanTool\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"field\":\"count\",\"transform\":{\"id\":\"1001\",\"type\":\"LogColorMapper\"}},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"units\":\"screen\",\"value\":10},\"x\":{\"field\":\"lon\"},\"y\":{\"field\":\"lat\"}},\"id\":\"1029\",\"type\":\"Circle\"},{\"attributes\":{\"dimension\":\"lon\"},\"id\":\"1008\",\"type\":\"MercatorTickFormatter\"},{\"attributes\":{\"callback\":null,\"data\":{\"count\":[80370,56570,50283,46286,45166,43779,41647,39243,33035,30195,30006,27599,27572,27084,26319,26110,25096,24079,23902,23825,23334,23010,22588,22525,21874,21350,19975,19962,19828,19773,19192,19089,19066,18403,18195,17044,16111,13051,12816,11336,10866,10415,9734,9688,9570,9350,9252,9134,8863,8414,8253,8219,7959,7866,7769,7391,7075,6819,6728,6542,6517,6264,5721,5688,5665,5658,5297,5257,5256,5193,5182,5078,4930,4794,4670,4319,4209,4201,4190,4076,4027,4016,4011,3880,3836,3794,3756,3742,3685,3512,3411,3382,3290,3283,3228,3182,3182,3111,3061,2988,2977,2930,2906,2905,2803,2794,2715,2699,2668,2664,2426,2342,2211,1990,1961,1895,1718,1476,1341,1229,1159,831,483,97,69,47],\"index\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125],\"lat\":{\"__ndarray__\":\"l0DT2fviQkC/1qVG6ONCQFNlzulo40JA2XsIfCPjQkBJ987DZONCQOP6VTdi40JAXuJ+dnbjQkB8XStGAuNCQHhi59XF4kJALsX6q2zjQkDayhzOreNCQOI5W0Bo40JAF2EzpI7jQkBDTZlAtuNCQBinnTr/4kJApWYPtALnQkABwLFnz+VCQMsRMpBn40JA+Z0mM97iQkDOYnMfyuJCQMfCa/Lv40JATALhpwvjQkDmxrIGUeNCQJKADqeG40JA2BpTRlfjQkBHrMWnAORCQGzPLAlQ40JA9CDzt/PiQkDkg57NquNCQEyL3vGn5EJAo4vycRLlQkDRfABS9uNCQO7of7kW5UJA0T3rGi3jQkDhYkUNpuVCQKTl5+vB5EJAggRr0FbkQkCVnBN7aOVCQIJnjCDf5EJA2qhOB7LiQkDKv2A4h+RCQA37PbFO5UJAQPmBg83kQkAXrGCcN+ZCQAOiFjn640JA8aKDvJfkQkAmqyLcZOZCQDPMgAPn5EJAxqS/l8LlQkBJLv8h/eRCQOR0SCAU5UJAoOBiRQ3mQkAVPIVcqeVCQFfMrbWc4kJAk6mCUUnlQkD1zNyNT+BCQNZIo08l5kJApN5TOe3hQkAgfY5vz+VCQI7Idyl14kJA1c+bilTkQkAwV/WoruNCQNWwa+U640JA2hGYmHjiQkBHHFfIAeNCQNh6K7dZ5EJAksIGVbThQkCrOn3Q2+NCQPREkPlT5EJApe8+sHbkQkA3gMhs2uFCQIQBlTt94UJAp6SYzS3hQkAAxoDVJeRCQCxfG7t14kJAggAZOnbhQkBX1pF+VuJCQEpuAy0T4kJATo5M0dvgQkCmtz8XDeRCQAT5I1aQ4kJAfdLkvcXhQkB5Q3XOquBCQCO70jJS40JArRbYYyLhQkDiOzHrxeRCQJqbyv1p4UJA5dlAFZLiQkBVdNoJ5eFCQCvXmtPj4UJALXzYZr7fQkAlLUsqCeNCQIuLo3IT4kJAAcaOIVvhQkAXlyVpSuRCQPQnO0cu4kJArU1jey3hQkB/qJjT7uBCQOaLYl7s4UJAz3KPW4LjQkDqLGl7quFCQBvs8lJW4UJAz1+NWDDiQkA8F0Z6UeFCQC0oZ4On30JAdUXfkz3fQkDUuaKUEOBCQGTpQxfU4UJAyr87njvgQkDnh7YIMd9CQN3BJAXi4UJATp4NVCHgQkAkfzDw3OFCQK+WOzPB4UJAwzhu57HhQkC17jA3KeJCQGJT4aAv4kJA00YagR3gQkB4sGq1LOFCQODuUSQE30JAUqDQ+j7kQkD6BPXSud9CQEq6mjCz4UJAKhThGhziQkAkC9AZyeJCQNZlOdmj4EJA\",\"dtype\":\"float64\",\"shape\":[126]},\"lon\":{\"__ndarray__\":\"AABASm+cXsBcAYV6+phewE7Nik1QmV7AAQAgazSaXsBNCdLWUppewAAAAJVHm17AAU7v4n2bXsCQNBNnoJpewAEAYPsIm17A0aEdgYmZXsAAD2yqIplewNI1k2+2ml7AAADg+gKaXsDiOQCH9ZtewAEAAClZm17AqKj6lc6ZXsAMPzifOplewKOs30xMmV7AkuCyr+GbXsAUocfewZtewBHRnoFHmV7AAACAlPWaXsB/B/bJw5lewP//P8O6m17A//9/ef+cXsC7YduizJpewCzxgLIpmV7AyXla2RmcXsAwDcNHxJpewP////PpmV7AIjgu46aZXsD//399lZlewBqmttRBmV7A0SFwJNCaXsDso1NXPplewAAPrJjWmF7AAAAA9iOaXsDE7GXbaZlewAcdGVAUmV7AxCKGHcaZXsAAAIDoZplewPFneLMGmV7AAAAAFW+ZXsABAGDWp5lewOTgLetZml7AwAPbqSuaXsDcaABvgZlewP///10lml7AZFjFG5mZXsBfYFYo0plewEm70cf8mF7AJGO1+X+ZXsCZ84x9yZlewNePA2UJmV7A6Zs0DYqZXsB2Mt2Q65pewP//fxf7mV7AobKr2v+aXsAAAIDB55lewGbH/JLDm17AwVYJFoeZXsDk3IGVnppewAAAAJxvmV7AHkZSHFGbXsDaci7F1ZlewPYmhuRkml7AgyM3eQCbXsAAPLDpy5lewP///8/Pm17A//9/8qeZXsA9dmG1w5lewH3wNV8AmV7AdiGxOPeaXsABAIDhH5xewP//f90Wml7ACddIt0qbXsDTbeQV45pewNgBIaNNm17AGXPXEvKaXsBsgC0KlppewNh6K7dZml7AVsimpm6aXsBVG/dB8ZpewC1b64sEnF7ATgrzHmeaXsCTjJyFPZlewLIY0Gawm17AFhl4SXebXsCQudfuQ5lewP//f8Ximl7Au2r53OSaXsBogGZrWJpewOmHbHuWm17AlJQFXYyaXsAAAAAXmJtewJW3I5yWml7A6E6w/zqaXsAAAABeF5lewPHg3YCFmV7AKYk2EUecXsBQ9ju5S5tewPJ9calKml7AcO1ESUiaXsCWI2Qgz5pewLE+1GxUml7AFcuIZvmaXsAwB4vUxZtewKFRFa6im17AOCFjpE2bXsBaj7HJUJtewAAAAJPgml7AWqyXlVyaXsDwxKwXQ5pewFwKo7SSml7A8o0yLJCbXsDwyXm1kplewAAAwCkSml7AATxYtVqbXsCfLTHg9ptewITzqWMVm17AAADASDCZXsDg77z5MptewAEAgHgSml7AAACAaH2ZXsAAAEAAgJlewAEAYB8/m17A\",\"dtype\":\"float64\",\"shape\":[126]},\"name\":[\"Central Ave at Fell St\",\"2nd St at Townsend St\",\"San Francisco Caltrain Station 2  (Townsend St at 4th St)\",\"8th St at Ringold St\",\"Howard St at 8th St\",\"Laguna St at Hayes St\",\"Webster St at Grove St\",\"11th St at Natoma St\",\"McCoppin St at Valencia St\",\"5th St at Brannan St\",\"3rd St at Townsend St\",\"Market St at 10th St\",\"Victoria Manalo Draves Park\",\"Scott St at Golden Gate Ave\",\"Koshland Park\",\"The Embarcadero at Sansome St\",\"San Francisco Ferry Building (Harry Bridges Plaza)\",\"San Francisco Caltrain (Townsend St at 4th St)\",\"Page St at Scott St\",\"Pierce St at Haight St\",\"S Park St at 3rd St\",\"Market St at Franklin St\",\"Bryant St at 6th St\",\"Alamo Square (Steiner St at Fulton St)\",\"Parker Ave at McAllister St\",\"Golden Gate Ave at Polk St\",\"Berry St at 4th St\",\"Broderick St at Oak St\",\"San Francisco City Hall (Polk St at Grove St)\",\"Powell St BART Station (Market St at 4th St)\",\"Montgomery St BART Station (Market St at 2nd St)\",\"4th St at Harrison St\",\"Howard St at Beale St\",\"S Van Ness Ave at Market St\",\"Steuart St at Market St\",\"The Embarcadero at Bryant St\",\"Powell St BART Station (Market St at 5th St)\",\"Embarcadero BART Station (Beale St at Market St)\",\"Beale St at Harrison St\",\"Townsend St at 7th St\",\"2nd St at Folsom St\",\"The Embarcadero at Steuart St\",\"Howard St at 2nd St\",\"Broadway at Battery St\",\"Civic Center/UN Plaza BART Station (Market St at McAllister St)\",\"Cyril Magnin St at Ellis St\",\"The Embarcadero at Vallejo St\",\"Union Square (Powell St at Post St)\",\"Clay St at Battery St\",\"Post St at Kearny St\",\"Spear St at Folsom St\",\"Davis St at Jackson St\",\"Commercial St at Montgomery St\",\"4th St at Mission Bay Blvd S\",\"Mechanics Monument Plaza (Market St at Bush St)\",\"Valencia St at 24th St\",\"Broadway at Kearny\",\"Valencia St at 16th St\",\"Washington St at Kearny St\",\"Duboce Park\",\"Folsom St at 3rd St\",\"San Francisco Public Library (Grove St at Hyde St)\",\"Townsend St at 5th St\",\"Market St at Dolores St\",\"7th St at Brannan St\",\"Father Alfred E Boeddeker Park\",\"17th St at Valencia St\",\"5th St at Folsom\",\"Raymond Kimbell Playground\",\"Yerba Buena Center for the Arts (Howard St at 3rd St)\",\"Rhode Island St at 17th St\",\"Esprit Park\",\"Mission Playground\",\"O'Farrell St at Divisadero St\",\"Division St at Potrero Ave\",\"Mission Dolores Park\",\"14th St at Mission St\",\"Dolores St at 15th St\",\"Valencia St at 21st St\",\"Golden Gate Ave at Hyde St\",\"11th St at Bryant St\",\"Harrison St at 17th St\",\"Valencia St at 22nd St\",\"Grove St at Divisadero\",\"Harrison St at 20th St\",\"1st St at Folsom St\",\"18th St at Noe St\",\"Church St at Duboce Ave\",\"Mississippi St at 17th St\",\"16th St Mission BART Station 2\",\"Valencia St at Cesar Chavez St\",\"Folsom St at 9th St\",\"Sanchez St at 15th St\",\"Folsom St at 19th St\",\"Webster St at O'Farrell St\",\"Folsom St at 15th St\",\"20th St at Bryant St\",\"22nd St Caltrain Station\",\"Jackson Playground\",\"McAllister St at Baker St\",\"17th St at Dolores St\",\"19th St at Florida St\",\"Bryant St at 15th St\",\"19th St at Mission St\",\"Precita Park\",\"29th St at Tiffany Ave\",\"Jersey St at Castro St\",\"16th St at Prosper St\",\"24th St at Chattanooga St\",\"29th St at Church St\",\"16th St Mission BART\",\"Garfield Square (25th St at Harrison St)\",\"Franklin Square\",\"17th & Folsom Street Park (17th St at Folsom St)\",\"Sanchez St at 17th St\",\"Irwin St at 8th St\",\"15th St at Potrero Ave\",\"Jersey St at Church St\",\"Eureka Valley Recreation Center\",\"30th St at San Jose Ave\",\"Bryant St at 2nd St\",\"Cesar Chavez St at Dolores St\",\"Potrero Ave and Mariposa St\",\"Hubbell St at 16th St\",\"Berry St at King St\",\"22nd St at Dolores St\"],\"station_id\":[70,50,67,60,61,74,55,77,76,64,66,58,62,39,56,6,15,30,72,73,49,75,63,54,51,41,81,71,42,3,21,47,22,59,16,28,5,17,27,90,37,23,25,9,44,4,8,324,14,19,24,11,13,93,20,134,323,98,10,84,36,43,80,86,79,34,109,321,31,284,114,126,121,29,89,120,97,96,127,33,88,112,133,53,129,26,119,85,116,223,141,78,95,123,285,99,125,130,115,52,107,124,100,122,144,147,137,105,132,145,108,139,113,110,106,102,101,138,118,146,343,140,336,345,91,131]},\"selected\":{\"id\":\"1039\",\"type\":\"Selection\"},\"selection_policy\":{\"id\":\"1040\",\"type\":\"UnionRenderers\"}},\"id\":\"1027\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"dimension\":\"lat\"},\"id\":\"1013\",\"type\":\"MercatorTickFormatter\"},{\"attributes\":{\"formatter\":{\"id\":\"1013\",\"type\":\"MercatorTickFormatter\"},\"plot\":{\"id\":\"1005\",\"subtype\":\"GMap\",\"type\":\"GMapPlot\"},\"ticker\":{\"id\":\"1014\",\"type\":\"MercatorTicker\"}},\"id\":\"1015\",\"type\":\"LinearAxis\"},{\"attributes\":{\"data_source\":{\"id\":\"1027\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"1029\",\"type\":\"Circle\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1030\",\"type\":\"Circle\"},\"selection_glyph\":null,\"view\":{\"id\":\"1032\",\"type\":\"CDSView\"}},\"id\":\"1031\",\"type\":\"GlyphRenderer\"}],\"root_ids\":[\"1005\"]},\"title\":\"Bokeh Application\",\"version\":\"1.0.4\"}};\n",
       "  var render_items = [{\"docid\":\"ad50ef3a-52f0-401b-9c09-8bac8448aa7f\",\"roots\":{\"1005\":\"4b4a4364-ad09-476f-a8ae-62d00dce8bda\"}}];\n",
       "  root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        embed_document(root);\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "      attempts++;\n",
       "      if (attempts > 100) {\n",
       "        console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "1005"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from bokeh.io import output_file, output_notebook, show\n",
    "from bokeh.models import (\n",
    "  GMapPlot, GMapOptions, ColumnDataSource, Circle, LogColorMapper, BasicTicker, ColorBar,\n",
    "    DataRange1d, PanTool, WheelZoomTool, BoxSelectTool, HoverTool\n",
    ")\n",
    "from bokeh.plotting import gmap\n",
    "from bokeh.models.mappers import ColorMapper, LogColorMapper\n",
    "from bokeh.palettes import Viridis6\n",
    "\n",
    "api_key=!curl -s http://metadata/computeMetadata/v1/instance/attributes/api_key -H \"Metadata-Flavor: Google\"\n",
    "api_key=api_key[0]\n",
    "\n",
    "color_mapper = LogColorMapper(palette=Viridis6)\n",
    "map_options = GMapOptions(lat=37.775, lng=-122.42, map_type=\"roadmap\", zoom=13)\n",
    "plot = gmap(api_key, map_options=map_options)\n",
    "source = ColumnDataSource(sf_stations)\n",
    "\n",
    "plot.circle(x=\"lon\", y=\"lat\", size=10,\n",
    "            fill_color={'field': 'count', 'transform': color_mapper},\n",
    "            fill_alpha=0.8, source=source)\n",
    "\n",
    "hover = HoverTool(\n",
    "    tooltips = [\n",
    "        (\"name\", \"@name\"),\n",
    "        (\"loc\", \"(@lat, @lon)\"),\n",
    "        (\"count\", \"@count\")\n",
    "    ],\n",
    "    mode='mouse'\n",
    ")\n",
    "plot.add_tools(hover)\n",
    "\n",
    "output_notebook(hide_banner=True)\n",
    "show(plot)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
